跳到主要内容

word-break 和 overflow-wrap

· 阅读需 6 分钟

主要描述浏览器中文本换行,以及对比 word-breakoverflow-wrap 这两个CSS属性在防止文本溢出上的效果.

这里主要讨论的是英文的换行

浏览器中的内容换行是如何发生的

浏览器在允许的断点处执行内容换行,以最大程度地减少内容溢出。

不同语言的书写系统,默认的换行是不一样的,这里主要是看英文中的默认换行。

实时编辑器
function TextOverflow() {
  const wrapStyles = {
    // 覆盖系统样式,还原到默认属性
    overflowWrap: 'normal',
    wordBreak: 'normal',
  }

  const contentStyles = {
    width: '200px',
    border: '1px solid #000',
    marginTop: '20px',
  }

  // 为了测试,手动在中间添加一些常见的符号
  const createText = (split = '') => {
    return `is time to reeeeeeeeeeeeeeee${split}eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeest`
  }

  return (
    <div style={wrapStyles}>
      <div style={contentStyles}>{createText('')}</div>
      <div style={contentStyles}>{createText('.')}</div>
      <div style={contentStyles}>{createText('+')}</div>
      <div style={contentStyles}>{createText(' ')}</div>
      <div style={contentStyles}>{createText('-')}</div>
    </div>
  )
}
结果
Loading...

可以看到,英文语言系统中,空格 和 "-" 都是默认会换行的。

下面主要对比 word-breakoverflow-wrap 在防止文本溢出上的效果

word-break

word-break 指定了怎样在单词内断行。有以下几个可选值

  • normal (默认)
  • break-all: 可在任意字符间断行
  • keep-all: 文本不断行
  • break-word (已废弃)
实时编辑器
function TextOverflow() {
  const wrapStyles = {
    // 覆盖系统样式,还原到默认属性
    overflowWrap: 'normal',
    wordBreak: 'normal',
  }

  const createContentStyles = (wordBreak = 'normal') => {
    return {
      width: '200px',
      border: '1px solid #000',
      marginBottom: '20px',
      wordBreak,
    }
  }

  // 为了测试,手动在中间添加一些常见的符号
  const createText = (split = '') => {
    return `is time to reeeeeeeeeeeeeeee${split}eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeest`
  }

  return (
    <div style={wrapStyles}>
      <div>normal:</div>
      <div style={createContentStyles('normal')}>{createText()}</div>

      <div>break-all:</div>
      <div style={createContentStyles('break-all')}>{createText()}</div>

      <div>keep-all:</div>
      <div style={createContentStyles('keep-all')}>{createText()}</div>
    </div>
  )
}
结果
Loading...

overflow-wrap

信息

这个属性原本属于微软扩展的一个非标准、无前缀的属性,叫做 word-wrap,后来在大多数浏览器中以相同的名称实现。

目前它已被更名为 overflow-wrap,word-wrap 相当于其别称。

word-break 一样,overflow-wrap 也是用来设置浏览器是否应该在一个本来不能断开的字符串中插入换行符,以防止文本溢出其行向盒。

有以下几个可选值

  • normal (默认): 只能在正常的单词断点(例如两个单词之间的空格)处换行
  • anywhere: 会在任何时候换行, 在计算最小内容内在大小时,会考虑由单词换行引入的软换行机会
  • break-word: 会在任何时候换行, 在计算最小内容内在大小时,不会考虑由单词换行引入的软换行机会
实时编辑器
function TextOverflow() {
  const wrapStyles = {
    // 覆盖系统样式,还原到默认属性
    overflowWrap: 'normal',
    wordBreak: 'normal',
  }

  const createContentStyles = (overflowWrap = 'normal') => {
    return {
      width: '200px',
      border: '1px solid #000',
      marginBottom: '20px',
      overflowWrap,
    }
  }

  // 为了测试,手动在中间添加一些常见的符号
  const createText = (split = '') => {
    return `is time to reeeeeeeeeeeeeeee${split}eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeest`
  }

  return (
    <div style={wrapStyles}>
      <div>normal:</div>
      <div style={createContentStyles('normal')}>{createText()}</div>

      <div>anywhere:</div>
      <div style={createContentStyles('anywhere')}>{createText()}</div>

      <div>break-word:</div>
      <div style={createContentStyles('break-word')}>{createText()}</div>
    </div>
  )
}
结果
Loading...

anywhere 和 break-word 看起来效果是一样的,其实关键在于他们对于容器最小宽度的影响

实时编辑器
function TextOverflow() {
  const wrapStyles = {
    display: 'flex',
    gap: '20px',
    // 覆盖系统样式,还原到默认属性
    overflowWrap: 'normal',
    wordBreak: 'normal',
  }

  const createContentStyles = (overflowWrap = 'normal') => {
    return {
      width: 'min-content', // 这个很重要
      border: '1px solid #000',
      overflowWrap,
    }
  }

  const noBreakStyles = {
    whiteSpace: 'nowrap',
  }

  // 为了测试,手动在中间添加一些常见的符号
  const createText = () => {
    return (
      <>
        <div style={noBreakStyles}>is time to</div>
        <div>reeeeeeeeeest</div>
      </>
    )
  }

  return (
    <>
      <p>两边计算最小宽度的依据不同</p>

      <div style={wrapStyles}>
        <div>
          <div>anywhere:</div>
          <div style={createContentStyles('anywhere')}>{createText()}</div>
        </div>

        <div>
          <div>break-word:</div>
          <div style={createContentStyles('break-word')}>{createText()}</div>
        </div>
      </div>
    </>
  )
}
结果
Loading...

对比总结

word-breakoverflow-wrap 本质是一样的,都是在字符间插入换行符。

但与 word-break 相比,overflow-wrap 仅在无法将整个单词放在自己的行而不会溢出的情况下才会产生换行。

如果可以将整个溢出单词放入一行而不溢出其容器,则使用 overflow-wrap 会将整个溢出单词包装到其行中。仅当浏览器无法将其放置在新行而不溢出时,才会破坏该单词。

只有在特殊场景,或者是非常严格的断字要求时,会考虑 word-break 规则。(暂时没发现场景)

否则一般情况下,overflow-wrap 是已经够用了的。